package com.meepo.framework.design.recycler

import android.content.Context
import android.view.LayoutInflater
import android.view.ViewGroup
import androidx.recyclerview.widget.RecyclerView

abstract class LinearAdapter<T>(private val mContext: Context, initialItems: List<T> = ArrayList()) : RecyclerView.Adapter<ViewHolder>() {

    private val mInflater: LayoutInflater = LayoutInflater.from(mContext)

    private val mItems: ArrayList<T> = ArrayList(initialItems)

    override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): ViewHolder {

        val data = this.mItems[viewType]

        val view = mInflater.inflate(getItemLayoutId(data, viewType), parent, false)
        return ViewHolder(mContext, view!!)
    }

    abstract fun getItemLayoutId(item: T, position: Int): Int

    abstract fun bind(item: T, holder: ViewHolder, position: Int)

    override fun getItemCount(): Int {
        return this.mItems.size
    }

    override fun getItemViewType(position: Int): Int {
        return position
    }

    override fun onBindViewHolder(holder: ViewHolder, position: Int) {
        val data = this.mItems[position]
        bind(data, holder, position)
    }

    fun get(position: Int): T? {
        if (position < 0 || position > itemCount - 1) return null
        return this.mItems[position]
    }

    @Suppress("UNCHECKED_CAST")
    fun <V> getAll(): List<V> {
        if (this.mItems.isEmpty()) return arrayListOf()
        return this.mItems.map { t -> t as V }
    }

    fun insert(item: T, position: Int) {
        this.mItems.add(position, item)
        notifyItemInserted(position)
    }

    fun refresh(items: List<T>) {
        this.mItems.clear()
        this.mItems.addAll(items)
//        notifyItemRangeInserted(0, items.size)
        notifyDataSetChanged()
    }

    fun replace(position: Int, newItem: T) {
        this.mItems[position] = newItem
        notifyItemChanged(position)
    }

    fun clear() {
        this.mItems.clear()
        notifyItemRangeRemoved(0, mItems.size)
    }

    fun remove(position: Int, adapterPosition: Int) {
        this.mItems.removeAt(position)
        notifyItemRemoved(adapterPosition)
    }

    fun add(items: List<T>) {
        this.mItems.addAll(items)
        notifyItemRangeInserted(this.mItems.size - items.size, items.size)
    }
}